package com.my.lucky.service;

import cn.hutool.core.util.StrUtil;
import com.my.lucky.dto.StockAnalysisResult;
import com.my.lucky.entity.StockQueryRecord;
import com.my.lucky.model.Stock;
import com.my.lucky.repository.StockQueryRecordRepository;
import com.my.lucky.repository.StockRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 股票分析服务
 * 用于分析股票选出后的价格表现
 */
@Slf4j
@Service
public class StockAnalysisService {

    @Autowired
    private StockQueryRecordRepository stockQueryRecordRepository;

    @Autowired
    private StockRepository stockRepository;

    /**
     * 判断2个板块有交集
     *
     * @param str1
     * @param str2
     * @return
     */
    public static boolean hasIntersection(String str1, String str2) {
        // 分割第一个字符串
//        System.out.println("str1=="+str1);
//        System.out.println("str2=="+str2);
        String[] parts1 = str1.split(",");
        // 为第二个字符串创建Set以提高查询效率
//        Set<String> parts2Set = new HashSet<>(Arrays.asList(str2.split(",")));

        // 检查是否有共同元素
        for (String part : parts1) {
            if (str2.contains(part)) {
                return true; // 找到第一个匹配项就返回
            }
        }
        return false;
    }

    /**
     * 获取股票分析结果（支持分页）
     *
     * @param startDate     开始日期
     * @param endDate       结束日期
     * @param timeFilter    时间筛选（可选）
     * @param type          股票类型（可选）
     * @param market        市场筛选（可选）
     * @param stockSearch   股票代码/名称搜索（可选）
     * @param page          页码（从0开始）
     * @param size          每页大小
     * @param sortField     排序字段
     * @param sortDirection 排序方向
     * @return 分页的股票分析结果
     */
    public Page<StockAnalysisResult> getStockAnalysisResultsWithPagination(LocalDate startDate, LocalDate endDate, String timeFilter, Integer type, String market, String stockSearch, String conceptSearch, int page, int size, String sortField, String sortDirection) {
        // 获取所有结果
        List<StockAnalysisResult> allResults = getStockAnalysisResults(startDate, endDate, timeFilter, type, market, stockSearch, conceptSearch);

        // 应用排序
        if (sortField != null && !sortField.isEmpty()) {
            allResults = sortResults(allResults, sortField, sortDirection);
        }

        // 创建分页对象
        Pageable pageable = PageRequest.of(page, size);

        // 计算分页
        int start = (int) pageable.getOffset();
        int end = Math.min((start + pageable.getPageSize()), allResults.size());

        List<StockAnalysisResult> pageContent = allResults.subList(start, end);

        return new PageImpl<>(pageContent, pageable, allResults.size());
    }

    /**
     * 获取股票分析结果
     *
     * @param startDate     开始日期
     * @param endDate       结束日期
     * @param timeFilter    时间筛选（可选）
     * @param type          股票类型（可选）
     * @param market        市场筛选（可选）
     * @param stockSearch   股票代码/名称搜索（可选）
     * @param conceptSearch 概念板块搜索（可选）
     * @return 股票分析结果列表
     */
    public List<StockAnalysisResult> getStockAnalysisResults(LocalDate startDate, LocalDate endDate, String timeFilter, Integer type, String market, String stockSearch, String conceptSearch) {
        List<StockAnalysisResult> results = new ArrayList<>();
//        List<StockQueryRecord> queryRecords = getQueryRecords(startDate, endDate, timeFilter, type);
//        Map<LocalDate, List<StockQueryRecord>> collect = queryRecords.stream().collect(Collectors.groupingBy(e -> e.getQueryTime().toLocalDate()));
        List<StockQueryRecord> queryRecords = null;
        Map<String, Integer> stockOccurrenceMap = new HashMap<>();

        if (StrUtil.isNotBlank(stockSearch)) {
            queryRecords = getQueryRecords(startDate, endDate, timeFilter, type);
            // 计算出现次数
            for (StockQueryRecord record : queryRecords) {
                stockOccurrenceMap.put(record.getStockCode() + record.getWencaiKeyword().getId(),
                        stockOccurrenceMap.getOrDefault(record.getStockCode() + record.getWencaiKeyword().getId(), 0) + 1);
            }
        } else {
            List<StockQueryRecord> allRecords = getQueryRecords(startDate, endDate, timeFilter, type);
            // 计算每个股票的出现次数
            for (StockQueryRecord record : allRecords) {
                stockOccurrenceMap.put(record.getStockCode() + record.getWencaiKeyword().getId(),
                        stockOccurrenceMap.getOrDefault(record.getStockCode() + record.getWencaiKeyword().getId(), 0) + 1);
            }

//            // 按股票代码分组，每个股票只取最早的一条记录用于分析
//            queryRecords = allRecords.stream()
//                    .collect(Collectors.groupingBy(
//                            StockQueryRecord::getStockCode,
//                            Collectors.collectingAndThen(
//                                    Collectors.toList(),
//                                    list -> list.stream()
//                                            .min(Comparator.comparing(StockQueryRecord::getQueryTime))
//                                            .orElse(list.get(0))
//                            )
//                    ))
//                    .values()
//                    .stream()
//                    .collect(Collectors.toList());

            // 按股票代码+wencaiKeyword组合分组，每个组合只取最早的一条记录
            queryRecords = allRecords.stream()
                    .collect(Collectors.groupingBy(
                            // 使用SimpleEntry作为组合键，包含stockCode和wencaiKeyword
                            record -> new AbstractMap.SimpleEntry<>(
                                    record.getStockCode(),
                                    record.getWencaiKeyword().getId()
                            ),
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    list -> list.stream()
                                            .min(Comparator.comparing(StockQueryRecord::getQueryTime))
                                            .orElse(list.get(0))
                            )
                    ))
                    .values()
                    .stream()
                    .collect(Collectors.toList());
        }
        LocalDate today = LocalDate.now();
        List<Map<String, Object>> maps = stockRepository.aggregateMainCapitalFlowByCodeAndDateRange(today.minusDays(7), today);
        // 查询指定时间范围内的股票查询记录
//        Map<String, BigDecimal> collect = maps.stream().collect(Collectors.toMap(e -> (String) e.get("code"), e -> (BigDecimal) e.get("totalMainFlow")));
        Map<String, BigDecimal> collect = maps.stream().filter(e -> e.get("code") != null) // 过滤空键
                .collect(Collectors.toMap(
                        e -> (String) e.get("code"),
                        e -> (BigDecimal) e.get("totalMainFlow")
                ));


        for (StockQueryRecord record : queryRecords) {
            try {
                // 应用股票代码/名称搜索筛选
                if (stockSearch != null && !stockSearch.trim().isEmpty()) {
                    String searchTerm = stockSearch.trim().toLowerCase();
                    String stockCode = record.getStockCode() != null ? record.getStockCode().toLowerCase() : "";
                    String stockName = record.getStockName() != null ? record.getStockName().toLowerCase() : "";

                    // 如果股票代码或名称都不包含搜索词，则跳过
                    if (!stockCode.contains(searchTerm) && !stockName.contains(searchTerm) && !searchTerm.contains(stockCode) && !searchTerm.contains(stockName)) {
                        continue;
                    }
                }

                // 应用概念板块搜索筛选
                if (conceptSearch != null && !conceptSearch.trim().isEmpty()) {
                    String conceptTerm = conceptSearch.trim().toLowerCase();
                    String allconcept = (record.getGainian() + "," + record.getAllGainian()) != null ? (record.getGainian() + "," + record.getAllGainian()).toLowerCase() : "";

                    // 使用方法是否有交集
                    boolean hasIntersection = hasIntersection(conceptTerm, allconcept);

                    // 如果概念板块不包含搜索词，则跳过
                    if (!allconcept.contains(conceptTerm) && !hasIntersection) {
//                    if (!hasIntersection) {
                        continue;
                    }
                }

                // 应用市场筛选
                if (market != null && !market.isEmpty()) {
                    if ("gem".equals(market) && !isGemStock(record.getStockCode())) {
                        continue; // 跳过非创业板股票
                    }
                }

                StockAnalysisResult result = analyzeStockPerformance(record);
                if (result != null) {
                    // 设置出现次数
                    result.setOccurrenceCount(stockOccurrenceMap.getOrDefault(record.getStockCode() + record.getWencaiKeyword().getId(), 1));
                    result.setSevenDaysMainFlow(collect.get(record.getStockCode()));
                    results.add(result);
                    // 设置7天
                }
            } catch (Exception e) {
                log.error("分析股票 {} 时出错: {}", record.getStockCode(), e.getMessage());
            }
        }

        return results;
    }

    /**
     * 获取股票分析结果
     *
     * @param startDate   开始日期
     * @param endDate     结束日期
     * @param timeFilter  时间筛选（可选）
     * @param type        股票类型（可选）
     * @param market      市场筛选（可选）
     * @param stockSearch 股票代码/名称搜索（可选）
     * @return 股票分析结果列表
     */
    public List<StockAnalysisResult> getStockCountAnalysisResults(LocalDate startDate, LocalDate endDate, String timeFilter, Integer type, String market, String stockSearch, String conceptSearch) {
        List<StockAnalysisResult> results = new ArrayList<>();
//        List<StockQueryRecord> queryRecords = getQueryRecords(startDate, endDate, timeFilter, type);
//        Map<LocalDate, List<StockQueryRecord>> collect = queryRecords.stream().collect(Collectors.groupingBy(e -> e.getQueryTime().toLocalDate()));
        List<StockQueryRecord> queryRecords = null;

        if (StrUtil.isNotBlank(stockSearch)) {
//            queryRecords = getQueryRecords(startDate, endDate, timeFilter, type);
        } else {
            queryRecords = getQueryRecordsCount(startDate, endDate, timeFilter, type)
                    .stream()
                    .collect(Collectors.groupingBy(
                            StockQueryRecord::getStockCode,
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    list -> list.stream()
                                            .min(Comparator.comparing(StockQueryRecord::getQueryTime))
                                            .orElse(list.get(0))
                            )
                    ))
                    .values()
                    .stream()
                    .collect(Collectors.toList());
        }
        // 查询指定时间范围内的股票查询记录


        for (StockQueryRecord record : queryRecords) {
            try {
                // 应用股票代码/名称搜索筛选
                if (stockSearch != null && !stockSearch.trim().isEmpty()) {
                    String searchTerm = stockSearch.trim().toLowerCase();
                    String stockCode = record.getStockCode() != null ? record.getStockCode().toLowerCase() : "";
                    String stockName = record.getStockName() != null ? record.getStockName().toLowerCase() : "";

                    // 如果股票代码或名称都不包含搜索词，则跳过
                    if (!stockCode.contains(searchTerm) && !stockName.contains(searchTerm)) {
                        continue;
                    }
                }

                // 应用市场筛选
                if (market != null && !market.isEmpty()) {
                    if ("gem".equals(market) && !isGemStock(record.getStockCode())) {
                        continue; // 跳过非创业板股票
                    }
                }

                StockAnalysisResult result = analyzeStockPerformance(record);
                if (result != null) {
                    results.add(result);
                }
            } catch (Exception e) {
                log.error("分析股票 {} 时出错: {}", record.getStockCode(), e.getMessage());
            }
        }

        return results;
    }

    /**
     * 获取股票分析结果（保持向后兼容）
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @param type      股票类型（可选）
     * @param market    市场筛选（可选）
     * @return 股票分析结果列表
     */
    public List<StockAnalysisResult> getStockAnalysisResults(LocalDate startDate, LocalDate endDate, Integer type, String market) {
        return getStockAnalysisResults(startDate, endDate, null, type, market, null, null);
    }

    /**
     * 获取股票分析结果（保持向后兼容）
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @param type      股票类型（可选）
     * @return 股票分析结果列表
     */
    public List<StockAnalysisResult> getStockAnalysisResults(LocalDate startDate, LocalDate endDate, Integer type) {
        return getStockAnalysisResults(startDate, endDate, null, type, null, null, null);
    }

    /**
     * 根据条件查询股票查询记录
     */
    private List<StockQueryRecord> getQueryRecords(LocalDate startDate, LocalDate endDate, String timeFilter, Integer type) {
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(23, 59, 59);

        // 如果有时间筛选，需要调整结束时间
        if (timeFilter != null && !timeFilter.trim().isEmpty()) {
            try {
                String[] timeParts = timeFilter.trim().split(":");
                if (timeParts.length == 2) {
                    int hour = Integer.parseInt(timeParts[0]);
                    int minute = Integer.parseInt(timeParts[1]);
                    // 对每天都应用时间限制：在查询时，我们需要确保每天都只查询到指定时间前的数据
                    // 但由于endDate可能跨多天，这里我们只能修改最后一天的时间
                    // 对于中间的天数，需要在后续处理中进行筛选
                    if (startDate.equals(endDate)) {
                        // 单天查询，直接设置时间限制
                        endDateTime = endDate.atTime(hour, minute);
                    }
                    // 多天查询的情况，在下面的查询结果中进行时间筛选
                }
            } catch (Exception e) {
                log.warn("解析时间筛选参数失败: {}", timeFilter, e);
            }
        }

        List<StockQueryRecord> records = new ArrayList<>();
        if (type != null) {
            if (type == 5 || type == 6 || type == 7 || type == 8) {//取交集 差值  涨停
                LocalDateTime fstartDateTime = startDate.atStartOfDay();
                LocalDateTime fendDateTime = startDate.atTime(23, 59, 59);
                LocalDateTime SstartDateTime = endDate.atStartOfDay();
                LocalDateTime SendDateTime = endDate.atTime(23, 59, 59);
//                System.out.println(fstartDateTime+"=="+fendDateTime+"=="+SstartDateTime+"=="+SendDateTime);
                if (type == 5) {
                    records = stockQueryRecordRepository.findIntersectionRecords(fstartDateTime, fendDateTime, SstartDateTime, SendDateTime);
                } else if (type == 6) {
                    records = stockQueryRecordRepository.findFDifferenceRecords(fstartDateTime, fendDateTime, SstartDateTime, SendDateTime);
                } else if (type == 7) {
                    records = stockQueryRecordRepository.findFDifferenceRecords(SstartDateTime, SendDateTime, fstartDateTime, fendDateTime);
                } else if (type == 8) {
                    records = stockQueryRecordRepository.findLimitedRecords(startDateTime, endDateTime);
                }
            } else {
                records = stockQueryRecordRepository.findByQueryTimeBetweenAndTypeOrderByQueryTimeAsc(startDateTime, endDateTime, type);
            }
        } else {
            records = stockQueryRecordRepository.findByQueryTimeBetweenOrderByQueryTimeAsc(startDateTime, endDateTime);
        }

        // 如果有时间筛选且是多天查询，需要在这里进行额外的时间筛选
        if (timeFilter != null && !timeFilter.trim().isEmpty() && !startDate.equals(endDate)) {
            try {
                String[] timeParts = timeFilter.trim().split(":");
                if (timeParts.length == 2) {
                    int hour = Integer.parseInt(timeParts[0]);
                    int minute = Integer.parseInt(timeParts[1]);

                    records = records.stream()
                            .filter(record -> {
                                LocalDateTime queryTime = record.getQueryTime();
                                int recordHour = queryTime.getHour();
                                int recordMinute = queryTime.getMinute();

                                // 检查是否在指定时间之前
                                return recordHour < hour || (recordHour == hour && recordMinute <= minute);
                            })
                            .collect(Collectors.toList());
                }
            } catch (Exception e) {
                log.warn("应用时间筛选失败: {}", timeFilter, e);
            }
        }

        return records;
    }

    /**
     * 根据条件查询股票查询记录
     */
    private List<StockQueryRecord> getQueryRecordsCount(LocalDate startDate, LocalDate endDate, String timeFilter, Integer type) {
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(23, 59, 59);

        // 如果有时间筛选，需要调整结束时间
        if (timeFilter != null && !timeFilter.trim().isEmpty()) {
            try {
                String[] timeParts = timeFilter.trim().split(":");
                if (timeParts.length == 2) {
                    int hour = Integer.parseInt(timeParts[0]);
                    int minute = Integer.parseInt(timeParts[1]);
                    // 对每天都应用时间限制：在查询时，我们需要确保每天都只查询到指定时间前的数据
                    // 但由于endDate可能跨多天，这里我们只能修改最后一天的时间
                    // 对于中间的天数，需要在后续处理中进行筛选
                    if (startDate.equals(endDate)) {
                        // 单天查询，直接设置时间限制
                        endDateTime = endDate.atTime(hour, minute);
                    }
                    // 多天查询的情况，在下面的查询结果中进行时间筛选
                }
            } catch (Exception e) {
                log.warn("解析时间筛选参数失败: {}", timeFilter, e);
            }
        }

        List<StockQueryRecord> recordss = new ArrayList<>();
//        List<Object[]>  records;
//        if (type != null) {
//            records = stockQueryRecordRepository.findByQueryTimeBetweenAndTypeOrderByQueryTimeAsc(startDateTime, endDateTime, type);
//        } else {
//            records = stockQueryRecordRepository.findByQueryTimeBetweenAndGroupByStockCodeOrderByCountDesc(startDateTime, endDateTime);
//        }

        recordss = stockQueryRecordRepository.findStockQueryStats(startDateTime, endDateTime);
        System.out.println(recordss);

        // 如果有时间筛选且是多天查询，需要在这里进行额外的时间筛选
//        if (timeFilter != null && !timeFilter.trim().isEmpty() && !startDate.equals(endDate)) {
        if (recordss != null) {
            try {
//                String[] timeParts = timeFilter.trim().split(":");
//                if (timeParts.length == 2) {
//                    int hour = Integer.parseInt(timeParts[0]);
//                    int minute = Integer.parseInt(timeParts[1]);

//                    recordss = recordss.stream()
//                            .map(arr -> {
//                                StockQueryRecord record = new StockQueryRecord();
//                                record.setStockCode((String) arr[0]);
//                                record.setQueryTime((LocalDateTime) arr[1]);
//                                record.setQueryCount(String.valueOf(arr[2]));
//                                return record;
//                            }).collect(Collectors.toList());


//                    records = records.stream()
//                            .filter(record -> {
//                                LocalDateTime queryTime = record.getQueryTime();
//                                int recordHour = queryTime.getHour();
//                                int recordMinute = queryTime.getMinute();
//
//                                // 检查是否在指定时间之前
//                                return recordHour < hour || (recordHour == hour && recordMinute <= minute);
//                            })
//                            .collect(Collectors.toList());
//                }
            } catch (Exception e) {
                log.warn("应用时间筛选失败: {}", timeFilter, e);
            }
        }

        return recordss;
    }

    /**
     * 分析单个股票的表现
     */
    private StockAnalysisResult analyzeStockPerformance(StockQueryRecord record) {
        String stockCode = normalizeStockCode(record.getStockCode());
        LocalDate queryDate = record.getQueryTime().toLocalDate();

        // 获取选出时的价格
        Double selectedPrice = parsePrice(record.getPrice());

        // 创建分析结果对象
        StockAnalysisResult result = new StockAnalysisResult(
                record.getStockCode(),
                record.getStockName(),
                record.getQueryTime(),
                selectedPrice,
                record.getChangePercent(),
                record.getWencaiKeyword().getId(),
                record.getWencaiKeyword().getKeyword(),
                record.getGainian(),
                record.getAllGainian(),
                record.getType(),
                record.getRankPosition(),
                record.getOldRankPosition(),
                record.getMainCapitalFlow(),
                record.getCapitalFlow()
        );

        // 查询从queryDate开始的前3条股票数据（处理交易日跳跃）
        List<Stock> stocksThreeDays = stockRepository.findTop3ByCodeAndTradeDateGreaterThanEqualOrderByTradeDateAsc(
                stockCode, queryDate);

        // 按顺序设置价格数据
        if (stocksThreeDays.size() >= 1) {
            // 第一条数据：当天收盘价
            result.setFirstDayPrice(stocksThreeDays.get(0).getClose());
        }

        if (stocksThreeDays.size() >= 2) {
            // 第二条数据：第二个交易日最高价
            result.setSecondDayHighPrice(stocksThreeDays.get(1).getHigh());
        }

        if (stocksThreeDays.size() >= 3) {
            // 第三条数据：第三个交易日最高价
            result.setThirdDayHighPrice(stocksThreeDays.get(2).getHigh());
        }

        // 计算涨幅
        result.calculateGainPercents();

        return result;
    }

    /**
     * 标准化股票代码（去掉cn_前缀）
     */
    private String normalizeStockCode(String code) {
        if (code.startsWith("cn_")) {
            return code.substring(3);
        }
        return code;
    }

    /**
     * 根据股票代码和日期查找股票数据
     */
    private Stock findStockByDate(String stockCode, LocalDate date) {
        List<Stock> stocks = stockRepository.findByCodeAndTradeDateBetweenOrderByTradeDateAsc(
                stockCode, date, date);
        return stocks.isEmpty() ? null : stocks.get(0);
    }

    /**
     * 解析价格字符串为Double
     */
    private Double parsePrice(String priceStr) {
        if (priceStr == null || priceStr.trim().isEmpty() || "-".equals(priceStr.trim())) {
            return null;
        }
        try {
            return Double.parseDouble(priceStr.trim());
        } catch (NumberFormatException e) {
            log.warn("无法解析价格字符串: {}", priceStr);
            return null;
        }
    }

    /**
     * 获取统计信息
     */
    public StockAnalysisStatistics getStatistics(List<StockAnalysisResult> results) {
        StockAnalysisStatistics stats = new StockAnalysisStatistics();

        if (results.isEmpty()) {
            return stats;
        }

        stats.setTotalCount(results.size());

        int firstDayPositive = 0;
        int secondDayPositive = 0;
        int thirdDayPositive = 0;
        int maxGainPositive = 0;

        double firstDayTotal = 0;
        double secondDayTotal = 0;
        double thirdDayTotal = 0;
        double maxGainTotal = 0;

        int firstDayCount = 0;
        int secondDayCount = 0;
        int thirdDayCount = 0;
        int maxGainCount = 0;

        for (StockAnalysisResult result : results) {
            if (result.getFirstDayGainPercent() != null) {
                firstDayTotal += result.getFirstDayGainPercent();
                firstDayCount++;
                if (result.getFirstDayGainPercent() > 0) {
                    firstDayPositive++;
                }
            }

            if (result.getSecondDayGainPercent() != null) {
                secondDayTotal += result.getSecondDayGainPercent();
                secondDayCount++;
                if (result.getSecondDayGainPercent() > 0) {
                    secondDayPositive++;
                }
            }

            if (result.getThirdDayGainPercent() != null) {
                thirdDayTotal += result.getThirdDayGainPercent();
                thirdDayCount++;
                if (result.getThirdDayGainPercent() > 0) {
                    thirdDayPositive++;
                }
            }

            if (result.getMaxGainPercent() != null) {
                maxGainTotal += result.getMaxGainPercent();
                maxGainCount++;
                if (result.getMaxGainPercent() > 0) {
                    maxGainPositive++;
                }
            }
        }

        if (firstDayCount > 0) {
            stats.setFirstDayAverageGain(firstDayTotal / firstDayCount);
            stats.setFirstDayPositiveRate((double) firstDayPositive / firstDayCount * 100);
        }

        if (secondDayCount > 0) {
            stats.setSecondDayAverageGain(secondDayTotal / secondDayCount);
            stats.setSecondDayPositiveRate((double) secondDayPositive / secondDayCount * 100);
        }

        if (thirdDayCount > 0) {
            stats.setThirdDayAverageGain(thirdDayTotal / thirdDayCount);
            stats.setThirdDayPositiveRate((double) thirdDayPositive / thirdDayCount * 100);
        }

        if (maxGainCount > 0) {
            stats.setMaxGainAverageGain(maxGainTotal / maxGainCount);
            stats.setMaxGainPositiveRate((double) maxGainPositive / maxGainCount * 100);
        }

        return stats;
    }

    /**
     * 对结果进行排序
     */
    private List<StockAnalysisResult> sortResults(List<StockAnalysisResult> results, String sortField, String sortDirection) {
        boolean ascending = "asc".equalsIgnoreCase(sortDirection);

        switch (sortField) {
            case "selectedTime":
                results.sort((a, b) -> {
                    if (a.getSelectedTime() == null && b.getSelectedTime() == null) return 0;
                    if (a.getSelectedTime() == null) return ascending ? -1 : 1;
                    if (b.getSelectedTime() == null) return ascending ? 1 : -1;
                    return ascending ? a.getSelectedTime().compareTo(b.getSelectedTime()) : b.getSelectedTime().compareTo(a.getSelectedTime());
                });
                break;
            case "firstDayGain":
                results.sort((a, b) -> {
                    Double aGain = a.getFirstDayGainPercent();
                    Double bGain = b.getFirstDayGainPercent();
                    if (aGain == null && bGain == null) return 0;
                    if (aGain == null) return ascending ? -1 : 1;
                    if (bGain == null) return ascending ? 1 : -1;
                    return ascending ? aGain.compareTo(bGain) : bGain.compareTo(aGain);
                });
                break;
            case "selectedPrice":
                results.sort((a, b) -> {
                    Double aGain = a.getSelectedPrice();
                    Double bGain = b.getSelectedPrice();
                    if (aGain == null && bGain == null) return 0;
                    if (aGain == null) return ascending ? -1 : 1;
                    if (bGain == null) return ascending ? 1 : -1;
                    return ascending ? aGain.compareTo(bGain) : bGain.compareTo(aGain);
                });
                break;
            case "secondDayGain":
                results.sort((a, b) -> {
                    Double aGain = a.getSecondDayGainPercent();
                    Double bGain = b.getSecondDayGainPercent();
                    if (aGain == null && bGain == null) return 0;
                    if (aGain == null) return ascending ? -1 : 1;
                    if (bGain == null) return ascending ? 1 : -1;
                    return ascending ? aGain.compareTo(bGain) : bGain.compareTo(aGain);
                });
                break;
            case "thirdDayGain":
                results.sort((a, b) -> {
                    Double aGain = a.getThirdDayGainPercent();
                    Double bGain = b.getThirdDayGainPercent();
                    if (aGain == null && bGain == null) return 0;
                    if (aGain == null) return ascending ? -1 : 1;
                    if (bGain == null) return ascending ? 1 : -1;
                    return ascending ? aGain.compareTo(bGain) : bGain.compareTo(aGain);
                });
                break;
            case "maxGain":
                results.sort((a, b) -> {
                    Double aGain = a.getMaxGainPercent();
                    Double bGain = b.getMaxGainPercent();
                    if (aGain == null && bGain == null) return 0;
                    if (aGain == null) return ascending ? -1 : 1;
                    if (bGain == null) return ascending ? 1 : -1;
                    return ascending ? aGain.compareTo(bGain) : bGain.compareTo(aGain);
                });
                break;
            case "occurrenceCount":
                results.sort((a, b) -> {
                    Integer aCount = a.getOccurrenceCount();
                    Integer bCount = b.getOccurrenceCount();
                    if (aCount == null && bCount == null) return 0;
                    if (aCount == null) return ascending ? -1 : 1;
                    if (bCount == null) return ascending ? 1 : -1;
                    return ascending ? aCount.compareTo(bCount) : bCount.compareTo(aCount);
                });
                break;
            case "searchangePercent":
                results.sort((a, b) -> {
                    Double aPercent = a.getSearchangePercent();
                    Double bPercent = b.getSearchangePercent();
                    if (aPercent == null && bPercent == null) return 0;
                    if (aPercent == null) return ascending ? -1 : 1;
                    if (bPercent == null) return ascending ? 1 : -1;
                    return ascending ? aPercent.compareTo(bPercent) : bPercent.compareTo(aPercent);
                });
                break;
            case "rankPosition":
//                以上改为默认升序
                results.sort((a, b) -> {
                    Long aPercent = a.getRankPosition();
                    Long bPercent = b.getRankPosition();
                    // 处理两个值都为null的情况
                    if (aPercent == null && bPercent == null) {
                        return 0;
                    }
                    // 处理aPercent为null的情况，默认升序时，null值应排在后
                    if (aPercent == null) {
                        return 1;
                    }
                    // 处理bPercent为null的情况，默认升序时，null值应排在后
                    if (bPercent == null) {
                        return -1;
                    }
                    // 两者都不为null时，直接比较数值大小，默认升序
                    return ascending ? Long.compare(bPercent, aPercent) : Long.compare(aPercent, bPercent);
                });
                break;
            case "mainCapitalFlow":
//                以上改为默认升序
                results.sort((a, b) -> {
                    BigDecimal aPercent = a.getMainCapitalFlow();
                    BigDecimal bPercent = b.getMainCapitalFlow();

                    // 处理两个值都为null的情况
                    if (aPercent == null && bPercent == null) {
                        return 0;
                    }
                    // 处理aPercent为null的情况，降序时null值应排在后
                    if (aPercent == null) {
                        return 1;
                    }
                    // 处理bPercent为null的情况，降序时null值应排在前
                    if (bPercent == null) {
                        return -1;
                    }
                    // 两者都不为null时，按数值大小降序排序
//                    return bPercent.longValue().compareTo(aPercent);
//                    return Double.compare(bPercent.doubleValue(), aPercent.doubleValue());
                    return ascending ?
                            Double.compare(aPercent.doubleValue(), bPercent.doubleValue()) :
                            Double.compare(bPercent.doubleValue(), aPercent.doubleValue());
                });
                break;
            case "concept":
                results.sort((a, b) -> {
                    String aPercent = a.getConcept();
                    String bPercent = b.getConcept();
                    if (aPercent == null && bPercent == null) return 0;
                    if (aPercent == null) return ascending ? -1 : 1;
                    if (bPercent == null) return ascending ? 1 : -1;
                    return ascending ? aPercent.compareTo(bPercent) : bPercent.compareTo(aPercent);
                });
                break;
            case "typeDescription":
                results.sort((a, b) -> {
                    String aPercent = a.getTypeDescription();
                    String bPercent = b.getTypeDescription();
                    if (aPercent == null && bPercent == null) return 0;
                    if (aPercent == null) return ascending ? -1 : 1;
                    if (bPercent == null) return ascending ? 1 : -1;
                    return ascending ? aPercent.compareTo(bPercent) : bPercent.compareTo(aPercent);
                });
                break;
            case "stockCode":
                results.sort((a, b) -> {
                    String aPercent = a.getStockCode();
                    String bPercent = b.getStockCode();
                    if (aPercent == null && bPercent == null) return 0;
                    if (aPercent == null) return ascending ? -1 : 1;
                    if (bPercent == null) return ascending ? 1 : -1;
                    return ascending ? aPercent.compareTo(bPercent) : bPercent.compareTo(aPercent);
                });
                break;
            case "allconcept":
                results.sort((a, b) -> {
                    String aPercent = a.getAllconcept();
                    String bPercent = b.getAllconcept();
                    if (aPercent == null && bPercent == null) return 0;
                    if (aPercent == null) return ascending ? -1 : 1;
                    if (bPercent == null) return ascending ? 1 : -1;
                    return ascending ? aPercent.compareTo(bPercent) : bPercent.compareTo(aPercent);
                });
                break;
            default:
                // 默认按选出时间升序排序
                results.sort((a, b) -> {
                    if (a.getSelectedTime() == null && b.getSelectedTime() == null) return 0;
                    if (a.getSelectedTime() == null) return 1;
                    if (b.getSelectedTime() == null) return -1;
                    return a.getSelectedTime().compareTo(b.getSelectedTime());
                });
                break;
        }

        return results;
    }

    /**
     * 判断是否为创业板股票
     * 创业板股票代码以30开头
     */
    private boolean isGemStock(String stockCode) {
        if (stockCode == null) return false;

        // 处理带前缀的股票代码
        String normalizedCode = normalizeStockCode(stockCode);

        // 创业板股票代码以30开头
        return normalizedCode.startsWith("30");
    }

    /**
     * 获取股票分析结果（批量查询优化版本）
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @param type      股票类型（可选）
     * @param market    市场筛选（可选）
     * @return 股票分析结果列表
     */
    public List<StockAnalysisResult> getStockAnalysisResultsOptimized(LocalDate startDate, LocalDate endDate, Integer type, String market) {
        List<StockAnalysisResult> results = new ArrayList<>();

        // 查询指定时间范围内的股票查询记录
        List<StockQueryRecord> queryRecords = getQueryRecords(startDate, endDate, type).stream()
                .collect(Collectors.groupingBy(
                        StockQueryRecord::getStockCode,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> list.get(0)
                        )
                ))
                .values()
                .stream()
                .collect(Collectors.toList());

        if (queryRecords.isEmpty()) {
            return results;
        }

        // 批量查询所有相关的股票数据
        Map<String, Map<LocalDate, Stock>> stockDataMap = batchQueryStockData(queryRecords);

        for (StockQueryRecord record : queryRecords) {
            try {
                // 应用市场筛选
                if (market != null && !market.isEmpty()) {
                    if ("gem".equals(market) && !isGemStock(record.getStockCode())) {
                        continue; // 跳过非创业板股票
                    }
                }

                StockAnalysisResult result = analyzeStockPerformanceOptimized(record, stockDataMap);
                if (result != null) {
                    results.add(result);
                }
            } catch (Exception e) {
                log.error("分析股票 {} 时出错: {}", record.getStockCode(), e.getMessage());
            }
        }

        return results;
    }

    /**
     * 批量查询股票数据，减少数据库访问次数
     */
    private Map<String, Map<LocalDate, Stock>> batchQueryStockData(List<StockQueryRecord> queryRecords) {
        // 收集所有需要查询的股票代码和日期范围
        Set<String> stockCodes = new HashSet<>();
        LocalDate minDate = null;
        LocalDate maxDate = null;

        for (StockQueryRecord record : queryRecords) {
            String normalizedCode = normalizeStockCode(record.getStockCode());
            stockCodes.add(normalizedCode);

            LocalDate queryDate = record.getQueryTime().toLocalDate();
            LocalDate endDate = queryDate.plusDays(7); // 最多查询到第七天

            if (minDate == null || queryDate.isBefore(minDate)) {
                minDate = queryDate;
            }
            if (maxDate == null || endDate.isAfter(maxDate)) {
                maxDate = endDate;
            }
        }

        // 一次性批量查询所有股票数据
        List<Stock> allStocks = stockRepository.findByCodesAndTradeDateBetween(
                new ArrayList<>(stockCodes), minDate, maxDate);

        // 按股票代码和日期组织数据
        Map<String, Map<LocalDate, Stock>> stockDataMap = new HashMap<>();
        for (Stock stock : allStocks) {
            stockDataMap.computeIfAbsent(stock.getCode(), k -> new HashMap<>())
                    .put(stock.getTradeDate(), stock);
        }

        return stockDataMap;
    }

    /**
     * 分析单个股票的表现（优化版本，使用预加载的数据）
     */
    private StockAnalysisResult analyzeStockPerformanceOptimized(StockQueryRecord record,
                                                                 Map<String, Map<LocalDate, Stock>> stockDataMap) {
        String stockCode = normalizeStockCode(record.getStockCode());
        LocalDate queryDate = record.getQueryTime().toLocalDate();

        // 获取选出时的价格
        Double selectedPrice = parsePrice(record.getPrice());

        // 创建分析结果对象
        StockAnalysisResult result = new StockAnalysisResult(
                record.getStockCode(),
                record.getStockName(),
                record.getQueryTime(),
                selectedPrice,
                record.getChangePercent(),
                record.getWencaiKeyword().getId(),
                record.getWencaiKeyword().getKeyword(),
                record.getGainian(),
                record.getAllGainian(),
                record.getType(),
                record.getRankPosition(),
                record.getOldRankPosition(),
                record.getMainCapitalFlow(),
                record.getCapitalFlow()
        );

        // 从预加载的数据中获取股票信息
        Map<LocalDate, Stock> stocksByDate = stockDataMap.get(stockCode);
        if (stocksByDate == null) {
            return result; // 没有找到股票数据
        }

        // 从预加载的数据中获取从queryDate开始的前3条股票数据（按日期排序）
        List<Stock> stocksThreeDays = stocksByDate.entrySet().stream()
                .filter(entry -> !entry.getKey().isBefore(queryDate)) // 从queryDate开始
                .sorted(Map.Entry.comparingByKey()) // 按日期升序排序
                .limit(3) // 只取前3条
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        // 按顺序设置价格数据
        if (stocksThreeDays.size() >= 1) {
            // 第一条数据：当天收盘价
            result.setFirstDayPrice(stocksThreeDays.get(0).getClose());
        }

        if (stocksThreeDays.size() >= 2) {
            // 第二条数据：第二个交易日最高价
            result.setSecondDayHighPrice(stocksThreeDays.get(1).getHigh());
        }

        if (stocksThreeDays.size() >= 3) {
            // 第三条数据：第三个交易日最高价
            result.setThirdDayHighPrice(stocksThreeDays.get(2).getHigh());
        }

        // 计算涨幅
        result.calculateGainPercents();

        return result;
    }

    /**
     * 获取股票分析结果（支持分页，优化版本）
     *
     * @param startDate     开始日期
     * @param endDate       结束日期
     * @param type          股票类型（可选）
     * @param market        市场筛选（可选）
     * @param page          页码（从0开始）
     * @param size          每页大小
     * @param sortField     排序字段
     * @param sortDirection 排序方向
     * @return 分页的股票分析结果
     */
    public Page<StockAnalysisResult> getStockAnalysisResultsWithPaginationOptimized(LocalDate startDate, LocalDate endDate, Integer type, String market, int page, int size, String sortField, String sortDirection) {
        // 使用优化版本获取所有结果
        List<StockAnalysisResult> allResults = getStockAnalysisResultsOptimized(startDate, endDate, type, market);

        // 应用排序
        if (sortField != null && !sortField.isEmpty()) {
            allResults = sortResults(allResults, sortField, sortDirection);
        }

        // 创建分页对象
        Pageable pageable = PageRequest.of(page, size);

        // 计算分页
        int start = (int) pageable.getOffset();
        int end = Math.min((start + pageable.getPageSize()), allResults.size());

        List<StockAnalysisResult> pageContent = allResults.subList(start, end);

        return new PageImpl<>(pageContent, pageable, allResults.size());
    }

    /**
     * 缓存优化版本（需要添加Redis依赖和配置）
     * 可以缓存批量查询的股票数据以减少重复查询
     */
    private Map<String, Map<LocalDate, Stock>> batchQueryStockDataWithCache(Set<String> stockCodes, LocalDate startDate, LocalDate endDate) {
        List<Stock> allStocks = stockRepository.findByCodesAndTradeDateBetween(
                new ArrayList<>(stockCodes), startDate, endDate);

        Map<String, Map<LocalDate, Stock>> stockDataMap = new HashMap<>();
        for (Stock stock : allStocks) {
            stockDataMap.computeIfAbsent(stock.getCode(), k -> new HashMap<>())
                    .put(stock.getTradeDate(), stock);
        }

        return stockDataMap;
    }

    /**
     * 根据条件查询股票查询记录（保持向后兼容）
     */
    private List<StockQueryRecord> getQueryRecords(LocalDate startDate, LocalDate endDate, Integer type) {
        return getQueryRecords(startDate, endDate, null, type);
    }

    /**
     * 统计信息内部类
     */
    public static class StockAnalysisStatistics {
        private int totalCount;
        private double firstDayAverageGain;
        private double secondDayAverageGain;
        private double thirdDayAverageGain;
        private double maxGainAverageGain;
        private double firstDayPositiveRate;
        private double secondDayPositiveRate;
        private double thirdDayPositiveRate;
        private double maxGainPositiveRate;

        // Getters and setters
        public int getTotalCount() {
            return totalCount;
        }

        public void setTotalCount(int totalCount) {
            this.totalCount = totalCount;
        }

        public double getFirstDayAverageGain() {
            return firstDayAverageGain;
        }

        public void setFirstDayAverageGain(double firstDayAverageGain) {
            this.firstDayAverageGain = firstDayAverageGain;
        }

        public double getSecondDayAverageGain() {
            return secondDayAverageGain;
        }

        public void setSecondDayAverageGain(double secondDayAverageGain) {
            this.secondDayAverageGain = secondDayAverageGain;
        }

        public double getThirdDayAverageGain() {
            return thirdDayAverageGain;
        }

        public void setThirdDayAverageGain(double thirdDayAverageGain) {
            this.thirdDayAverageGain = thirdDayAverageGain;
        }

        public double getMaxGainAverageGain() {
            return maxGainAverageGain;
        }

        public void setMaxGainAverageGain(double maxGainAverageGain) {
            this.maxGainAverageGain = maxGainAverageGain;
        }

        public double getFirstDayPositiveRate() {
            return firstDayPositiveRate;
        }

        public void setFirstDayPositiveRate(double firstDayPositiveRate) {
            this.firstDayPositiveRate = firstDayPositiveRate;
        }

        public double getSecondDayPositiveRate() {
            return secondDayPositiveRate;
        }

        public void setSecondDayPositiveRate(double secondDayPositiveRate) {
            this.secondDayPositiveRate = secondDayPositiveRate;
        }

        public double getThirdDayPositiveRate() {
            return thirdDayPositiveRate;
        }

        public void setThirdDayPositiveRate(double thirdDayPositiveRate) {
            this.thirdDayPositiveRate = thirdDayPositiveRate;
        }

        public double getMaxGainPositiveRate() {
            return maxGainPositiveRate;
        }

        public void setMaxGainPositiveRate(double maxGainPositiveRate) {
            this.maxGainPositiveRate = maxGainPositiveRate;
        }
    }
} 